/*
* Copyright (c) 2008, Vladimir Gumenuk
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the copyright holder nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// LeftView.cpp : implementation of the CLeftView class
//

#include "stdafx.h"
#include "RealGNX4Lib.h"

#include "RealGNX4LibDoc.h"
#include "LeftView.h"
#include "RealGNX4LibView.h"
#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CLeftView

IMPLEMENT_DYNCREATE(CLeftView, CListView)

BEGIN_MESSAGE_MAP(CLeftView, CListView)
    ON_NOTIFY_RANGE(LVN_ITEMCHANGED, 0, 0xffff, OnListItemChanged)
    ON_NOTIFY_RANGE(NM_RCLICK, 0, 0xffff, OnListRBtnClick)
    ON_WM_DROPFILES()
    ON_WM_DESTROY()
END_MESSAGE_MAP()


// CLeftView construction/destruction

CLeftView::CLeftView()
{
	m_pRightView = NULL;
}

CLeftView::~CLeftView()
{
}

BOOL CLeftView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying the CREATESTRUCT cs

	return CListView::PreCreateWindow(cs);
}

void CLeftView::OnInitialUpdate()
{
	CListView::OnInitialUpdate();
    
    USES_CONVERSION;
	// TODO: You may populate your TreeView with items by directly accessing
	//  its tree control through a call to GetTreeCtrl().
    CListCtrl& lst = GetListCtrl();
    lst.ModifyStyle( LVS_LIST|LVS_ICON, LVS_REPORT|LVS_SINGLESEL );
    lst.SetExtendedStyle( LVS_EX_FLATSB|LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_SNAPTOGRID );
    lst.InsertColumn( 0, _T("#"), LVCFMT_LEFT, 20 );
    lst.InsertColumn( 1, _T("Name"), LVCFMT_LEFT, 100 );

    CRealGNX4LibDoc* pDoc = GetDocument();
    LPPRESET pPreset = pDoc->GetPresets();

    for( DWORD i = 0; i < GNX_MAX_PRESETS; i++ )
    {
        LPPRESET pPR = &pPreset[i];
        char szBuf[16];
        sprintf_s( szBuf, "%d", i+1 );
        int idx = lst.InsertItem( i, szBuf );
        lst.SetItemText( idx, 1, W2T( pPR->wszName ) );
    }

    lst.SetItemState( 0, LVIS_SELECTED, LVIS_SELECTED );

    DragAcceptFiles( TRUE );
} 

void CLeftView::OnDestroy()
{
    DragAcceptFiles( FALSE );
    CListView::OnDestroy();
}

// CLeftView diagnostics

#ifdef _DEBUG
void CLeftView::AssertValid() const
{
	CListView::AssertValid();
}

void CLeftView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}

CRealGNX4LibDoc* CLeftView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CRealGNX4LibDoc)));
	return (CRealGNX4LibDoc*)m_pDocument;
}
#endif //_DEBUG

// CLeftView message handlers
void CLeftView::OnListItemChanged( UINT id, NMHDR* pNotifyStruct, LRESULT* pResult )
{
    LPNMLISTVIEW pNMLv = (LPNMLISTVIEW)pNotifyStruct;
    ASSERT( pNMLv != NULL );
    ASSERT( m_pRightView );

    if( pNMLv->uChanged == LVIF_STATE && (pNMLv->uNewState & LVIS_SELECTED) )
    {
        m_pRightView->OnPresetSelected( pNMLv->iItem );
    }

    *pResult = 0;
}

void CLeftView::OnListRBtnClick( UINT id, NMHDR* pNotifyStruct, LRESULT* pResult )
{
    CMenu menu;
    menu.LoadMenu( IDR_RealGNX4LibTYPE );
    CMenu *pPrMenu = menu.GetSubMenu( 3 );

    CPoint pt;
    GetCursorPos( &pt );

    pPrMenu->TrackPopupMenu( TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, GetMainFrame() );
    *pResult = 0;
}

int CLeftView::GetSelectedPreset() // -1 or preset number
{
    int nItem = -1;

    CListCtrl& lst = GetListCtrl();
    UINT iCount = lst.GetSelectedCount();
    if( iCount > 0 )
    {
        nItem = lst.GetNextItem( nItem, LVIS_SELECTED );
        ASSERT( nItem != -1 );
    }

    return nItem;
}

BOOL CLeftView::MovePresetUp()
{
    int iItem = GetSelectedPreset();
    if( iItem == -1 || iItem == 0 )
        return FALSE;

    CListCtrl& lst = GetListCtrl();
    CString csNameDown = lst.GetItemText( iItem-1, 1 );
    CString csNameUp   = lst.GetItemText( iItem, 1 );

    lst.SetItemText( iItem, 1, csNameDown );
    iItem--;
    lst.SetItemText( iItem, 1, csNameUp );
    lst.SetItemState( iItem, LVIS_SELECTED, LVIS_SELECTED );
    lst.EnsureVisible( iItem, FALSE );

    return TRUE;
}

BOOL CLeftView::MovePresetDown()
{
    int iItem = GetSelectedPreset();
    if( iItem == -1 || iItem == GNX_MAX_PRESETS-1 )
        return FALSE;

    CListCtrl& lst = GetListCtrl();
    CString csNameUp   = lst.GetItemText( iItem+1, 1 );
    CString csNameDown = lst.GetItemText( iItem, 1 );

    lst.SetItemText( iItem, 1, csNameUp );
    iItem++;
    lst.SetItemText( iItem, 1, csNameDown );
    lst.SetItemState( iItem, LVIS_SELECTED, LVIS_SELECTED );
    lst.EnsureVisible( iItem, FALSE );

    return TRUE;
}

void CLeftView::UpdatePreset( UINT iIdx )
{
    CListCtrl& lst = GetListCtrl();
    CRealGNX4LibDoc* pDoc = GetDocument();
    LPPRESET pPr = pDoc->GetPreset( iIdx );

    USES_CONVERSION;
    lst.SetItemText( iIdx, 1, W2A(pPr->wszName) );

    m_pRightView->OnPresetSelected( iIdx );
}

void CLeftView::OnDropFiles( HDROP hDropInfo )
{
    CPoint pt;
    if( !DragQueryPoint( hDropInfo, &pt ) )
        return;

    int iIdx = FindItemFromPoint( pt );
    if( iIdx == -1 )
        return;

    CListCtrl& lst = GetListCtrl();

    UINT iCount = DragQueryFile( hDropInfo, 0xFFFFFFFF, NULL, 0 );

    TRACE( "CLeftView::OnDropFiles -> %d files, start index: %d\n", iCount, iIdx );
    CHAR szBuf[512];

    for( UINT i = 0; i < iCount; i++ )
    {
        if( DragQueryFile( hDropInfo, i, szBuf, 512 ) )
        {
            TRACE( "CLeftView::OnDropFiles -> '%s'\n", szBuf );

            char *p = strrchr( szBuf, '.' );
            if( p && _stricmp( p, ".g4p" ) == 0 )
            {
                CRealGNX4LibDoc *pDoc = GetDocument();
                if( pDoc->LoadGP4FileToPreset( szBuf, iIdx ) )
                {
                    UpdatePreset( iIdx );

                    if( ++iIdx >= lst.GetItemCount() )
                        iIdx = 0;
                }
            }
        }
    }

    DragFinish( hDropInfo );
    
    iIdx--;
    lst.SetItemState( iIdx, LVIS_SELECTED, LVIS_SELECTED );
}

int CLeftView::FindItemFromPoint( const CPoint& pt )
{
    CListCtrl& lst = GetListCtrl();

    int iCount = lst.GetItemCount();
    for( int i = 0; i < iCount; i++ )
    {
        CRect rc;
        lst.GetItemRect( i, &rc, LVIR_BOUNDS );

        if( rc.PtInRect( pt ) )
            return i;
    }

    return -1;
}